﻿using System;
using OfficeOpenXml;
using System.Text.RegularExpressions;
using DimensionsHelper.Common.Contracts.Excel;
using DimensionsHelper.Common.Excel;

namespace DimensionsHelper.Services.Excel.EPPlus;

public partial class ExcelWorksheetOperator : IExcelWorksheetOperator
{
    private ExcelWorksheet Worksheet { get; }

    private ExcelWorksheetOperator(IExcelWorkbookOperator workbook, ExcelWorksheet worksheet)
    {
        Workbook = workbook;
        Worksheet = worksheet;
    }

    internal static ExcelWorksheetOperator Create(IExcelWorkbookOperator workbook, ExcelWorksheet worksheet)
    {
        return new ExcelWorksheetOperator(workbook, worksheet);
    }

    private string GetLegalSheetName(string sourceText)
    {
        var correct = SheetNameRegex().Replace(sourceText, "");

        if (correct.Length > 31)
        {
            correct = correct[..31];
            if (Worksheet.Workbook.Worksheets[correct] != null)
            {
                correct = correct[..^3];
                var count = 1;
                while (true)
                {
                    correct = $"{correct}({count})";
                    if (Worksheet.Workbook.Worksheets[correct] is null)
                    {
                        break;
                    }
                    count++;
                }
            }
        }

        return correct;
    }

    public IExcelWorkbookOperator Workbook { get; }

    public string Name
    {
        get => Worksheet.Name;
        set => Worksheet.Name = GetLegalSheetName(value);
    }

    public ExcelStyleColor TabColor
    {
        get => Worksheet.TabColor.ToExcelColor();
        set => Worksheet.TabColor = value.ToColor();
    }

    public int StartRow => Worksheet.Dimension.Start.Row;

    public int StartColumn => Worksheet.Dimension.Start.Column;

    public int EndRow => Worksheet.Dimension.End.Row;

    public int EndColumn => Worksheet.Dimension.End.Column;

    public bool ShowGridLines
    {
        get => Worksheet.View.ShowGridLines;
        set => Worksheet.View.ShowGridLines = value;
    }

    public int Zoom
    {
        get => Worksheet.View.ZoomScale;
        set => Worksheet.View.ZoomScale = value;
    }

    public void AutoFitEntireColumns()
    {
        Worksheet.Columns.AutoFit();
    }

    public void DeleteRow(int row)
    {
        Worksheet.DeleteRow(row);
    }

    public void DeleteColumn(int column)
    {
        Worksheet.DeleteColumn(column);
    }

    public string GetCellText(int row, int column)
    {
        return Worksheet.Cells[row, column].GetCellValue<string>() ?? string.Empty;
    }

    public object GetValues()
    {
        return Worksheet.Dimension != null
            ? Worksheet.Dimension.Value
            : Array.CreateInstance(typeof(object),
                [0, 0], [1, 1]);
    }

    public IExcelRangeOperator GetRange(int row, int column)
    {
        return ExcelRangeOperator.Create(this, Worksheet.Cells[row, column]);
    }

    public IExcelRangeOperator GetRange(int fromRow, int fromColumn, int toRow, int toColumn)
    {
        return ExcelRangeOperator.Create(this, Worksheet.Cells[fromRow, fromColumn, toRow, toColumn]);
    }

    public IExcelRangeOperator GetRow(int row)
    {
        return ExcelRangeOperator.Create(this, Worksheet.Cells[row, 1, row, Worksheet.Dimension.Columns]);
    }

    public void InsertRow(int row, int rows = 1)
    {
        if (rows <= 0 || row <= 0)
        {
            return;
        }

        Worksheet.InsertRow(row, rows);
    }

    public void MoveToStart()
    {
        Worksheet.Workbook.Worksheets.MoveToStart(Name);
    }

    public void MoveToEnd()
    {
        Worksheet.Workbook.Worksheets.MoveToEnd(Name);
    }

    public void SetColumnAlignment(int column, ExcelHAlign horizontalAlignment, ExcelVAlign verticalAlignment)
    {
        Worksheet.Columns[column].Style.HorizontalAlignment = ExcelRangeOperator.OperatorHorizontalAlignmentToExcelAlignment(horizontalAlignment);
        Worksheet.Columns[column].Style.VerticalAlignment = ExcelRangeOperator.OperatorVerticalAlignmentToExcelAlignment(verticalAlignment);
    }

    public void SetColumnAlignment(ExcelHAlign horizontalAlignment, ExcelVAlign verticalAlignment)
    {
        Worksheet.Columns.Style.HorizontalAlignment = ExcelRangeOperator.OperatorHorizontalAlignmentToExcelAlignment(horizontalAlignment);
        Worksheet.Columns.Style.VerticalAlignment = ExcelRangeOperator.OperatorVerticalAlignmentToExcelAlignment(verticalAlignment);
    }

    public void SetColumnWidth(double width)
    {
        Worksheet.Columns.Width = width;
    }

    public void SetColumnWidth(int column, double width)
    {
        Worksheet.Columns[column].Width = width;
    }

    [GeneratedRegex(@"[\\/?*\[\]]")]
    private static partial Regex SheetNameRegex();
}